﻿using System.Linq;
using System.Transactions;
using AspZone.Commerce.DataAccess;
using AspZone.Commerce.Model;
using AspZone.Commerce.Service;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NHibernate;

namespace AspZone.Commerce.IntegrationTests
{
    /// <summary>
    /// Summary description for AspZoneCommerceDataTests
    /// </summary>
    [TestClass]
    public class AspZoneCommerceDataTests
    {
        private TransactionScope transactionScope;
        private IAspZoneCommerceData aspZoneCommerceData;
        private ISession session;

        [TestInitialize]
        public void TestInitialize()
        {
            this.transactionScope = new TransactionScope();
            this.aspZoneCommerceData = new AspZoneCommerceData();
            this.session = ((AspZoneCommerceData)this.aspZoneCommerceData).Session;

            this.session.Delete("from Product");
            this.session.Delete("from Category");
            this.session.Flush();
            this.session.Clear();
        }

        [TestCleanup]
        public void TestCleanup()
        {
            this.transactionScope.Dispose();
            this.aspZoneCommerceData.Dispose();
        }

        [TestMethod]
        public void CategoriesSave_WhenPassedNewCategory_SavesCategory()
        {
            var c1 = new Category
            {
                Name = "Category Name",
                Hidden = true,
                LongDescription = "Long Description",
                SEOKeywords = "SEO Keywords",
                SEOName = "SEO+Name",
                SEOTitle = "SEO Title",
                ShortDescription = "Short Description",
                SortOrder = 12,
                Image = new Image { FullsizePath = "a", ThumbnailPath = "b" }
            };

            this.aspZoneCommerceData.Categories.Save(c1);
            this.aspZoneCommerceData.SubmitChanges();

            this.session.Clear();
            var result = this.session.Get<Category>(c1.Id);
            Assert.IsNotNull(result);
            Assert.AreEqual<string>(c1.Name, result.Name);
            Assert.AreEqual<bool>(c1.Hidden, result.Hidden);
            Assert.AreEqual<string>(c1.LongDescription, result.LongDescription);
            Assert.AreEqual<string>(c1.SEOKeywords, result.SEOKeywords);
            Assert.AreEqual<string>(c1.SEOName, result.SEOName);
            Assert.AreEqual<string>(c1.SEOTitle, result.SEOTitle);
            Assert.AreEqual<string>(c1.ShortDescription, result.ShortDescription);
            Assert.AreEqual<int>(c1.SortOrder, result.SortOrder);
            Assert.IsNotNull(result.Image);
            Assert.AreEqual<string>(c1.Image.FullsizePath, result.Image.FullsizePath);
            Assert.AreEqual<string>(c1.Image.ThumbnailPath, result.Image.ThumbnailPath);
        }

        [TestMethod]
        public void ProductsSave_WhenPassedNewProduct_SavesProduct()
        {
            // create a product, and load it up with all possible fields
            var p1 = new Product
            {
                Name = "Name",
                ShortDescription = "ShortDescription",
                LongDescription = "LongDescription",
                SEOTitle = "SEOTitle",
                SEOName = "SEOName",
                SEOKeywords = "a,b,c",
                Price = 1.99m,
                DiscountPercent = 0.15m,
                HandlingCharge = 9.99m,
                Weight = 0.29m,
                QuantityAvailable = 12
            };

            var c1 = new Category { Name = "1", SEOName = "1" };
            var c2 = new Category { Name = "2", SEOName = "2" };
            var c3 = new Category { Name = "3", SEOName = "3" };
            p1.Categories.Add(c1);
            p1.Categories.Add(c2);
            p1.Categories.Add(c3);

            // must save the categories seperately
            this.session.Save(c1);
            this.session.Save(c2);
            this.session.Save(c3);

            var i1 = new Image { FullsizePath = "1", ThumbnailPath = "1" };
            var i2 = new Image { FullsizePath = "2", ThumbnailPath = "2" };
            var i3 = new Image { FullsizePath = "3", ThumbnailPath = "3" };
            p1.Images.Add(i1);
            p1.Images.Add(i2);
            p1.Images.Add(i3);

            var pr1 = new ProductProperty { Name = "a", Value = "a" };
            var pr2 = new ProductProperty { Name = "b", Value = "b" };
            var pr3 = new ProductProperty { Name = "c", Value = "c" };
            p1.Properties.Add(pr1);
            p1.Properties.Add(pr2);
            p1.Properties.Add(pr3);

            this.aspZoneCommerceData.Products.Save(p1);
            this.aspZoneCommerceData.SubmitChanges();

            this.session.Clear();
            var result = this.session.Get<Product>(p1.Id);

            Assert.IsNotNull(result);
            Assert.AreEqual<string>(p1.Name, result.Name);
            Assert.AreEqual<string>(p1.ShortDescription, result.ShortDescription);
            Assert.AreEqual<string>(p1.LongDescription, result.LongDescription);
            Assert.AreEqual<string>(p1.SEOTitle, result.SEOTitle);
            Assert.AreEqual<string>(p1.SEOName, result.SEOName);
            Assert.AreEqual<string>(p1.SEOKeywords, result.SEOKeywords);
            Assert.AreEqual<decimal>(p1.Price, result.Price);
            Assert.AreEqual<decimal>(p1.DiscountPercent, result.DiscountPercent);
            Assert.AreEqual<decimal>(p1.HandlingCharge, result.HandlingCharge);
            Assert.AreEqual<decimal>(p1.Weight, result.Weight);
            Assert.AreEqual<int>(p1.QuantityAvailable, result.QuantityAvailable);

            Assert.AreEqual<int>(3, result.Categories.Count);
            
            Assert.AreEqual<int>(3, result.Images.Count);
            Assert.AreEqual<int>(1, result.Images.Count(i => i.FullsizePath == "1" && i.ThumbnailPath == "1"));
            Assert.AreEqual<int>(1, result.Images.Count(i => i.FullsizePath == "2" && i.ThumbnailPath == "2"));
            Assert.AreEqual<int>(1, result.Images.Count(i => i.FullsizePath == "3" && i.ThumbnailPath == "3"));

            Assert.AreEqual<int>(3, result.Properties.Count);
            Assert.AreEqual<int>(1, result.Properties.Count(p => p.Name == "a" && p.Value == "a"));
            Assert.AreEqual<int>(1, result.Properties.Count(p => p.Name == "b" && p.Value == "b"));
            Assert.AreEqual<int>(1, result.Properties.Count(p => p.Name == "c" && p.Value == "c"));
        }
    }
}
